package cn.com.anypay.manager.common.utils;

import org.springframework.stereotype.Component;

import java.net.InetAddress;
import java.net.UnknownHostException;
import java.security.SecureRandom;
import java.util.concurrent.atomic.AtomicLong;

/**
 * 分布式ID生成器
 * 适用于分布式环境下的唯一ID生成
 */
@Component
public class DistributedIdGenerator {

    private static final AtomicLong SEQUENCE = new AtomicLong(0);
    private static final SecureRandom RANDOM = new SecureRandom();
    private static final int MACHINE_ID;
    
    static {
        MACHINE_ID = generateMachineId();
    }

    /**
     * 生成机器ID
     * 基于IP地址生成机器标识
     */
    private static int generateMachineId() {
        try {
            InetAddress ip = InetAddress.getLocalHost();
            byte[] ipBytes = ip.getAddress();
            return ((ipBytes[ipBytes.length - 2] & 0xFF) << 8) | (ipBytes[ipBytes.length - 1] & 0xFF);
        } catch (UnknownHostException e) {
            // 如果无法获取IP，使用随机数
            return RANDOM.nextInt(65536);
        }
    }

    /**
     * 生成分布式ID
     * 格式：时间戳(41位) + 机器ID(16位) + 序列号(7位)
     * @return 分布式ID
     */
    public static long generateId() {
        long timestamp = System.currentTimeMillis();
        long sequence = SEQUENCE.getAndIncrement() & 0x7F; // 7位序列号
        
        return (timestamp << 23) | (MACHINE_ID << 7) | sequence;
    }

    /**
     * 生成字符串格式的分布式ID
     */
    public static String generateIdStr() {
        return String.valueOf(generateId());
    }

    /**
     * 生成带前缀的分布式ID
     * @param prefix 前缀
     * @return 带前缀的ID
     */
    public static String generateIdWithPrefix(String prefix) {
        return prefix + generateId();
    }

    /**
     * 生成Base36格式的分布式ID（更短）
     * @return Base36格式ID
     */
    public static String generateBase36Id() {
        return Long.toString(generateId(), 36).toUpperCase();
    }

    /**
     * 批量生成ID
     * @param count 生成数量
     * @return ID数组
     */
    public static long[] generateBatch(int count) {
        long[] ids = new long[count];
        for (int i = 0; i < count; i++) {
            ids[i] = generateId();
        }
        return ids;
    }

    /**
     * 获取当前机器ID
     */
    public static int getMachineId() {
        return MACHINE_ID;
    }
}